#!/usr/bin/env python 
# -*- coding: utf-8 -*-
"""
Copyright (C) 2010 Nayanajith laxaman 
GPL
"""

import os
import gtk,gtkhtml2,cairo
from gtk import Layout
import urllib
import pango, pangocairo, gobject
import urlparse
import re, codecs
import atk
import hashlib

import warnings
warnings.filterwarnings("ignore")


WINDOWS=( os.name == 'nt')
GDK_Escape = 0xff1b;
opener = urllib.FancyURLopener()
FONT = pango.FontDescription('KaputaUnicode 14')
currentUrl = None


PW_DIR = "/usr/share/reader-si"
if WINDOWS:
   PW_DIR=os.getcwd().replace("\\","/")
else:
   PW_DIR=os.getcwd()

TEXT_DIR = PW_DIR + "/text"   #keep the raw text file
HTML_DIR = PW_DIR + "/html"   #generated and keep the html files
DIGEST_FILE=PW_DIR+"/digest"  #digest file to check updates of the files
STYLE = "style.css"           #custom stylesheet for html files
CAT_DISC="category.txt"       #name of the category file to keep in directories of text folder to present the category name 
digest_dict={}                  #hash digest file will be loaded here to check with the files


class SiPaliReader():
   NEW_STYLE=False
   def focus_received(self, widget, data=None):
      self.focused = widget
      #print(widget.get_name())

   #change font of all children
   def changePango(self, child):
      if gobject.type_is_a(child,gtk.Container):
         for subChild in child.get_children():
            if not re.search(r'menubar|button|label|dialog-action_area', subChild.get_name()):
               self.changePango(subChild)
      else:
         child.modify_font(FONT)
   
   def file_open(self, widget, data=None):
      pass
   
   def file_save(self, widget, data=None):
      pass

   def file_save_as(self, widget, data=None):
      pass

   def file_new(self, widget, data=None):
      pass

   def edit_cut(self, widget, data=None):
      gtk.Editable.cut_clipboard(self.focused)
      
   def edit_copy(self, widget, data=None):
      gtk.Editable.copy_clipboard(self.focused)

   def edit_paste(self, widget, data=None):
      gtk.Editable.paste_clipboard(self.focused)

   def edit_delete(self, widget, data=None):
      gtk.Editable.delete_selection(self.focused)

   '''
   def link_clicked(self, widget, data=None):
      os.system("htmlview " + widget.get_url())
   '''

   #close app
   def gtk_main_quit(self, widget, data=None):
      gtk.main_quit()

   #close app
   def delete_event(self, widget, event, data=None):
      gtk.main_quit()
      return False

   def on_window1_remove(self, widget, data=None):
      gtk.main_quit()
     
   def search(self, widget, data=None):
      print "search"
      

   def key_pressed(self, widget, event, data=None):
      #~ print "%4x" % (event,keyval)
      if (event.keyval == GDK_Escape):
         gtk.main_quit()
   
   def help_about(self, widget, data=None):
      result = self.about.run()
      self.about.hide()

   def print_status(self, status):      
      self.label1.set_text(status)

#------------------------TXT2HTML----------------------------#
   '''
   Checking for updates
   '''
   def digest_load(self):
      if os.path.isfile(DIGEST_FILE):
         for line in codecs.open(DIGEST_FILE,"r","utf-8"):
	    params = line.rstrip("\n").rstrip("\r").rstrip(" ").split('::')
            digest_dict[params[0]] = params[1]

   def digest_write(self):
      file = codecs.open(DIGEST_FILE,"w","utf-8")
      for param in  digest_dict:
         file.write(param+"::"+digest_dict[param]+"\n")
      """
      for file1 in os.listdir(TEXT_DIR):
         if os.path.isdir(TEXT_DIR+"/"+file1):
            for file2 in os.listdir(TEXT_DIR+"/"+file1):
	       file.write(TEXT_DIR+"/"+file1+"/"+file2+"::"+hashlib.md5(open(TEXT_DIR+"/"+file1+"/"+file2,"r").read()).hexdigest()+"\n")
         else:
	    file.write(TEXT_DIR+"/"+file1+"::"+hashlib.md5(open(TEXT_DIR+"/"+file1,"r").read()).hexdigest()+"\n")
      """
      file.close()

   def digest_check(self,check_file):
      try:
         if digest_dict[check_file] ==  hashlib.md5(open(check_file,"r").read()).hexdigest():
            return True
         else:
            #print check_file
            digest_dict[check_file] = hashlib.md5(open(check_file,"r").read()).hexdigest()
            return False
      except:
         digest_dict[check_file] = hashlib.md5(open(check_file,"r").read()).hexdigest()
         return False
      
   '''
   Converting text to html by replacing '\n' with '<br/>', making the first line as 
   header and appending top and bottom to the HTML with style tag
   '''
   def txt2html(self, in_file, out_file):
      file = codecs.open(in_file,"r","utf-8")
      body = u""
      title = u""
      title_found = False

      for line in file.readlines():
         line = line.decode("UTF-8")
         if not title_found:
            if line == "" or line == "\n" or line == "\n\r" or re.match('^[\ ]*$', line):
               continue
            #removing Windows BOM_UTF8 character
            title = line.rstrip('\n').rstrip('\r').rstrip(' ').lstrip( unicode( codecs.BOM_UTF8, "utf8" ))
	    #print title[:1]
            line = "<center><h1>" + line + "</h1></center>"
            body += line.replace("\n", "<br/>")
            title_found = True
         else:
            body += line.replace("\n", "<br/>")

      file.close()

      style=u"""*{
color:green; 
font-size:20px;
font-family:KaputaUnicode,Arial,LKLUG;
}
h1{
font-size:30px;
font-weight:bold;
}"""
      if os.path.isfile(PW_DIR + "/" + STYLE):
         style=open(PW_DIR + "/" + STYLE, "r").read()

      html = u"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--html xmlns="http://www.w3.org/1999/xhtml" xml:lang="si_LK" lang="si_LK"-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html charset=utf-8" />
<!--link type="text/css" href="file:///""" + PW_DIR + "/" + STYLE + """ " rel="stylesheet"-->
<!--link type="text/css" href=" """ + STYLE + """ " rel="stylesheet"-->
<style>
""" + style + """
</style>
<title>""" + title + """</title>
</head>
<body>
<p>
<code>
""" + body + """
</code>
</p>
<center>෴</center>
</body>
</html>
"""

      file = codecs.open(out_file, "w", "UTF-8")
      file.write(html)
      file.close()

   '''
   Read all the files in the given TXT_DIR and convert them in to HTML and place in HTML_DIR
   This will do for sub directories also. These sub directories can be use as categories. 
   '''
   def convert_all_files(self):
      if not os.path.isdir(HTML_DIR):
         os.mkdir(HTML_DIR)

      for filename in os.listdir(TEXT_DIR):
         if os.path.isdir(TEXT_DIR + "/" + filename):
            if not os.path.isdir(HTML_DIR + "/" + filename):
               os.mkdir(HTML_DIR + "/" + filename)
            if not os.path.isfile(HTML_DIR + "/" + filename+"/"+CAT_DISC) and os.path.isfile(TEXT_DIR + "/" + filename+"/"+CAT_DISC) or not self.digest_check(TEXT_DIR + "/" + filename+"/"+CAT_DISC):
               codecs.open(HTML_DIR + "/" + filename+"/"+CAT_DISC,"w","UTF-8").write(codecs.open(TEXT_DIR + "/" + filename+"/"+CAT_DISC,"r","UTF-8").read())
            for filename2 in os.listdir(TEXT_DIR + "/" + filename):
               if filename2 == CAT_DISC:
                  continue
               if not os.path.isfile(HTML_DIR + "/" + filename + "/" + filename2 + ".html") or (not self.digest_check(TEXT_DIR + "/" + filename + "/" + filename2) or self.NEW_STYLE):
                  self.txt2html(TEXT_DIR + "/" + filename + "/" + filename2, HTML_DIR + "/" + filename + "/" + filename2 + ".html")
         else:
            if not os.path.isfile(HTML_DIR + "/" + filename + ".html") or (not self.digest_check(TEXT_DIR + "/" + filename) or self.NEW_STYLE):
               self.txt2html(TEXT_DIR + "/" + filename, HTML_DIR + "/" + filename + ".html")


#------------------------/TXT2HTML----------------------------#
#-----------------------HTML viewer--------------------------#

   def is_relative_to_server(self, url):
      parts = urlparse.urlparse(url)
      if parts[0] or parts[1]:
         return 0
      return 1

   def open_url(self, url):
      if re.search(r"file:", url):
         uri = url
      else:
         uri = self.resolve_uri(url)
      return opener.open(uri)

   def resolve_uri(self, uri):
      if self.is_relative_to_server(uri):
         return urlparse.urljoin(currentUrl, uri)
      return uri

   def request_url(self, document, url, stream):
      f = self.open_url(url)
      stream.write(f.read())

   def link_clicked(self, document, link):
      self.print_status('link_clicked:' + link)
      global currentUrl
      try:
         f = self.open_url(link)
      except OSError:
	 self.print_status( "failed to open:"+link)
         return
      currentUrl = self.resolve_uri(link)
      document.clear()
      headers = f.info()
      mime = headers.getheader('Content-type').split(';')[0]
      if mime:
         document.open_stream(mime)
      else:
         document.open_stream('text/plain')
      #removing Windows BOM_UTF8 character
      document.write_stream(f.read().replace(unicode( codecs.BOM_UTF8, "utf8" ),""))
      document.close_stream()

   def request_object(self, *args):
      self.print_status('request object:'+args)

#-----------------------/HTML viewer--------------------------#
#---------------------------Tree------------------------------#
   def build_index(self):
      for filename in os.listdir(HTML_DIR):
         if os.path.isdir(HTML_DIR + "/" + filename):
            category=u"නොදන්නා ගොනුවක්"
	    #Reading category
	    cat_file=codecs.open(HTML_DIR + "/" + filename +"/"+CAT_DISC,"r","utf-8")
	    for line in cat_file.readlines():
	       category=line.rstrip('\n').rstrip('\r').replace(unicode( codecs.BOM_UTF8, "utf8" ),"")
	    cat_file.close()
            piter = self.treestore1.append(None, [0,"-"+category+"-", HTML_DIR + "/" + filename])

            for filename2 in os.listdir(HTML_DIR + "/" + filename):
	       if filename2 == CAT_DISC:
	          continue

               title = filename2
               no = 0
               file = codecs.open(HTML_DIR + "/" + filename + "/" + filename2,"r","utf-8")
               for line in file.readlines():
                  line = line.rstrip('\n').rstrip('\r')
                  title_s = re.search(r"(?i)<title>\s*(.*?)\s*</title>", line)
                  if title_s:
                     title = title_s.groups()[0] 
                     no = re.search(r"\s*([0-9]*)\s*", title).groups()[0]
                     title =  re.sub(r""+no+"\.?","",title)
                     no = int(no)
                     break
               self.treestore1.append(piter, [no,title, HTML_DIR + "/" + filename + "/" + filename2])
               file.close()
         else:
            title = filename
            no = 0
            file = codecs.open(HTML_DIR + "/" + filename,"r","utf-8")
            for line in file.readlines():
               line = line.decode("UTF-8").rstrip('\n').rstrip('\r').rstrip(' ')
               title_s = re.search(r"(?i)<title>\s*(.*?)\s*</title>", line)
               if title_s:
                  title = title_s.groups()[0]
                  no = re.search(r"\s*([0-9]*)\s*", title).groups()[0]
                  title =  re.sub(r""+no+"\.?","",title)
                  no = int(no)
                  break
            self.treestore1.append(None, [no,title, HTML_DIR + "/" + filename])
            file.close()

      cell = gtk.CellRendererText()
      cell.set_property('font-desc',FONT)
      #column_name=u'ලිපිය'
      column1_name=u'No'
      column2_name=u'Title'
      self.tvcolumn1 = gtk.TreeViewColumn(column1_name,cell,text=0)
      self.tvcolumn2 = gtk.TreeViewColumn(column2_name,cell,text=1)
      self.treeview1.append_column(self.tvcolumn1)
      self.treeview1.append_column(self.tvcolumn2)
      self.treeview1.set_search_column(1)
      self.treeview1.set_reorderable(True)

      self.cell = gtk.CellRendererText()
      self.tvcolumn1.pack_start(self.cell, True)
      self.tvcolumn2.pack_start(self.cell, True)
      #self.tvcolumn.add_attribute(self.cell, 'text', 0)
      self.tvcolumn1.set_sort_column_id(0)
      self.tvcolumn2.set_sort_column_id(0)


   def on_treeview_cursor_changed(self, treeview):
      s = treeview.get_selection()
      (treestore, iter) = s.get_selected()
      if iter is None:
         print "nothing selected"
      else:
         no = treestore.get_value(iter, 0)
         topic = treestore.get_value(iter, 1)
         fname = treestore.get_value(iter, 2)
         self.print_status(fname)
	 #Check whether it is a directory
	 if os.path.isdir(fname):
	    return
	 if WINDOWS:
            self.link_clicked(self.document, "file:///" + fname)
         else:
            self.link_clicked(self.document, "file://" + fname)
         #treestore.set_value(iter, 1, data1 + 1)
         #print "Selected:", topic, fname

#--------------------------/Tree------------------------------#

   def __init__(self):
      builder = gtk.Builder()
      builder.add_from_file("reader-si.glade")

      self.window = builder.get_object("window1")
      self.entry1 = builder.get_object("entry1")
      self.label1 = builder.get_object("label1")
      self.about = builder.get_object("aboutdialog1")
      self.sw = builder.get_object("scrolledwindow1")
      self.sw2 = builder.get_object("scrolledwindow2")
      self.vpaned1 = builder.get_object("vpaned1")
      self.aboutdialog1 = builder.get_object("aboutdialog1")

      #setting fonts
      self.changePango(self.window)
      #self.changePango(self.aboutdialog1)
#---------------------------TXT2HTML------------------------------#
      self.digest_load()
      if os.path.isfile(PW_DIR + "/" + STYLE):
         self.NEW_STYLE=( not self.digest_check(PW_DIR + "/" + STYLE) )
      self.convert_all_files()
      self.digest_write()
#---------------------------/TXT2HTML------------------------------#
#---------------------------Tree------------------------------#
      self.treestore1 = gtk.TreeStore(int, str, str)
      self.treeview1 = gtk.TreeView(self.treestore1)
      self.sw2.add(self.treeview1)
      self.build_index()
#--------------------------/Tree------------------------------#

#-----------------------HTML viewer--------------------------#
      self.document = gtkhtml2.Document()
      self.document.connect('request_url', self.request_url)
      self.document.connect('link_clicked', self.link_clicked)
      self.document.clear()
      self.document.open_stream('text/html')
      intro_html = u"""<html>
<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<head>
<style>
*{
color:black; 
font-size:20px;
font-family:KaputaUnicode,Arial,LKLUG;
}
h1{
font-size:40px;
font-weight:bold;
}
</style>
</head>
<body>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
<center>
<h1>ආයුබෝවන්!</h1><br/>
<br/>
<br/>
<h2>- පූජ්‍යපාද මඩිහේ පඤ්ඤාසීහ හිමියන්ගේ ලිපි එකතුව -</h2>
<br/>
<br/>
</center>
</body>
</html>"""
      self.document.write_stream(intro_html)
      self.document.close_stream()

      self.view = gtkhtml2.View()
      self.view.set_document(self.document)
      self.view.connect('request_object', self.request_object)
      self.window.connect("delete_event", self.delete_event)

      self.sw.add(self.view)
#-----------------------/HTML viewer--------------------------#

      self.window.show_all()
      builder.connect_signals(self)
      self.entry1.connect("focus-in-event", self.focus_received)
      self.treeview1.connect("cursor-changed", self.on_treeview_cursor_changed)
      #self.sw.connect("focus-in-event", self.focus_received)
      self.focused = self.entry1



if __name__ == "__main__":
   sipalireader = SiPaliReader()
   sipalireader.window.show()
   gtk.main()
